﻿using System;
using System.Threading;
using Just4Devs.Vsirc.Addin.UI;
using Meebey.SmartIrc4net;


namespace Just4Devs.Vsirc.Addin
{
	public class VsircController
	{
		private IrcClient ircClient;
		private Thread _ircThread;
		private VsircScreenDirector screenDirector;
		private string serverName;

		public string ServerName
		{
			get { return serverName; }
		}

		public VsircController(VsircScreenDirector screenDirector)
		{
			this.screenDirector = screenDirector;
		}

		void Listen(object configuration)
		{
			try
			{
				var serverConfiguration = (VsircServerConfiguration)configuration;

				ircClient = new IrcClient();

				ircClient.ActiveChannelSyncing = true;
				ircClient.AutoRejoin = true;
				ircClient.SendDelay = 500;
				ircClient.OnBan += new BanEventHandler(ircClient_OnBan);
				ircClient.OnChannelAction += new ActionEventHandler(ircClient_OnChannelAction);
				ircClient.OnChannelActiveSynced += new IrcEventHandler(ircClient_OnChannelActiveSynced);
				ircClient.OnChannelMessage += new IrcEventHandler(ircClient_OnChannelMessage);
				ircClient.OnChannelModeChange += new IrcEventHandler(ircClient_OnChannelModeChange);
				ircClient.OnChannelNotice += new IrcEventHandler(ircClient_OnChannelNotice);
				ircClient.OnChannelPassiveSynced += new IrcEventHandler(ircClient_OnChannelPassiveSynced);
				ircClient.OnConnected += new EventHandler(ircClient_OnConnected);
				ircClient.OnConnecting += new EventHandler(ircClient_OnConnecting);
				ircClient.OnConnectionError += new EventHandler(ircClient_OnConnectionError);
				ircClient.OnCtcpReply += new IrcEventHandler(ircClient_OnCtcpReply);
				ircClient.OnCtcpRequest += new IrcEventHandler(ircClient_OnCtcpRequest);
				ircClient.OnDehalfop += new DehalfopEventHandler(ircClient_OnDehalfop);
				ircClient.OnDeop += new DeopEventHandler(ircClient_OnDeop);
				ircClient.OnDevoice += new DevoiceEventHandler(ircClient_OnDevoice);
				ircClient.OnDisconnected += new EventHandler(ircClient_OnDisconnected);
				ircClient.OnDisconnecting += new EventHandler(ircClient_OnDisconnecting);
				ircClient.OnError += new ErrorEventHandler(ircClient_OnError);
				ircClient.OnErrorMessage += new IrcEventHandler(ircClient_OnErrorMessage);
				ircClient.OnHalfop += new HalfopEventHandler(ircClient_OnHalfop);
				ircClient.OnInvite += new InviteEventHandler(ircClient_OnInvite);
				ircClient.OnJoin += new JoinEventHandler(ircClient_OnJoin);
				ircClient.OnKick += new KickEventHandler(ircClient_OnKick);
				ircClient.OnModeChange += new IrcEventHandler(ircClient_OnModeChange);
				ircClient.OnMotd += new MotdEventHandler(ircClient_OnMotd);
				ircClient.OnNames += new NamesEventHandler(ircClient_OnNames);
				ircClient.OnNickChange += new NickChangeEventHandler(ircClient_OnNickChange);
				ircClient.OnOp += new OpEventHandler(ircClient_OnOp);
				ircClient.OnPart += new PartEventHandler(ircClient_OnPart);
				ircClient.OnPing += new PingEventHandler(ircClient_OnPing);
				ircClient.OnQueryAction += new ActionEventHandler(ircClient_OnQueryAction);
				ircClient.OnQueryMessage += new IrcEventHandler(ircClient_OnQueryMessage);
				ircClient.OnQueryNotice += new IrcEventHandler(ircClient_OnQueryNotice);
				ircClient.OnQuit += new QuitEventHandler(ircClient_OnQuit);
				ircClient.OnRawMessage += new IrcEventHandler(ircClient_OnRawMessage);
				ircClient.OnRegistered += new EventHandler(ircClient_OnRegistered);
				ircClient.OnTopic += new TopicEventHandler(ircClient_OnTopic);
				ircClient.OnTopicChange += new TopicChangeEventHandler(ircClient_OnTopicChange);
				ircClient.OnUnban += new UnbanEventHandler(ircClient_OnUnban);
				ircClient.OnUserModeChange += new IrcEventHandler(ircClient_OnUserModeChange);
				ircClient.OnVoice += new VoiceEventHandler(ircClient_OnVoice);
				ircClient.OnWho += new WhoEventHandler(ircClient_OnWho);

				ircClient.Connect(serverConfiguration.Server, serverConfiguration.Port);
				ircClient.Login(serverConfiguration.OriginalNick, serverConfiguration.RealName);
				ircClient.RfcJoin(serverConfiguration.FirstChannel);

				ircClient.Listen();
			}
			catch (Exception ex)
			{
				var message = new ServerMessage("Fatal Error: " + ex.Message);

				screenDirector.RouteMessage(serverName, message);
			}
		}

		#region Irc Events

		void ircClient_OnVoice(object sender, VoiceEventArgs e)
		{

		}

		void ircClient_OnUserModeChange(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnUnban(object sender, UnbanEventArgs e)
		{

		}

		void ircClient_OnTopicChange(object sender, TopicChangeEventArgs e)
		{

		}

		void ircClient_OnRegistered(object sender, EventArgs e)
		{

		}

		void ircClient_OnQuit(object sender, QuitEventArgs e)
		{

		}

		void ircClient_OnQueryNotice(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnPing(object sender, PingEventArgs e)
		{

		}

		void ircClient_OnQueryAction(object sender, ActionEventArgs e)
		{

		}

		void ircClient_OnOp(object sender, OpEventArgs e)
		{

		}

		void ircClient_OnModeChange(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnInvite(object sender, InviteEventArgs e)
		{

		}

		void ircClient_OnHalfop(object sender, HalfopEventArgs e)
		{

		}

		void ircClient_OnDisconnecting(object sender, EventArgs e)
		{

		}

		void ircClient_OnDevoice(object sender, DevoiceEventArgs e)
		{

		}

		void ircClient_OnDeop(object sender, DeopEventArgs e)
		{

		}

		void ircClient_OnDehalfop(object sender, DehalfopEventArgs e)
		{

		}

		void ircClient_OnCtcpRequest(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnCtcpReply(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnChannelPassiveSynced(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnChannelActiveSynced(object sender, IrcEventArgs e)
		{
			var channel = ircClient.GetChannel(e.Data.Channel);
		}

		void ircClient_OnWho(object sender, WhoEventArgs e)
		{

		}

		void ircClient_OnNickChange(object sender, NickChangeEventArgs e)
		{

		}

		void ircClient_OnMotd(object sender, MotdEventArgs e)
		{
			var message = new MotdMessage(e.MotdMessage);

			screenDirector.RouteMessage(serverName, message);
		}

		void ircClient_OnChannelNotice(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnChannelModeChange(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnChannelAction(object sender, ActionEventArgs e)
		{

		}

		void ircClient_OnBan(object sender, BanEventArgs e)
		{

		}

		void ircClient_OnKick(object sender, KickEventArgs e)
		{

		}

		private bool EventWasCausedByUser(string who)
		{
			return who.Equals(ircClient.Nickname);
		}

		void ircClient_OnPart(object sender, PartEventArgs e)
		{
			if (!EventWasCausedByUser(e.Who))
			{
				var message = new PartMessage(e.Who);

				screenDirector.RouteMessage(e.Channel, message);
				ircClient.RfcNames(e.Channel);
			}
		}

		void ircClient_OnNames(object sender, NamesEventArgs e)
		{
			screenDirector.SetChannelUserList(e.Channel, e.UserList);
		}

		void ircClient_OnJoin(object sender, JoinEventArgs e)
		{
			try
			{
				if (EventWasCausedByUser(e.Who))
				{
					screenDirector.SelectTab(e.Channel);
					screenDirector.RouteMessage(e.Channel, new JoinMessage("You", e.Channel));
				}
				else
				{
					var message = new JoinMessage(e.Who, e.Channel);
					screenDirector.RouteMessage(e.Channel, message);
					ircClient.RfcNames(e.Channel);
				}
			}
			catch (ArgumentException ex)
			{
				var message = new ServerMessage(ex.Message);
				screenDirector.RouteMessage(serverName, message);
			}
		}

		void ircClient_OnQueryMessage(object sender, IrcEventArgs e)
		{
			var message = new PrivateMessage(e.Data.Nick, e.Data.Message);
			screenDirector.RouteMessage(e.Data.Nick, message);
		}

		void ircClient_OnRawMessage(object sender, IrcEventArgs e)
		{

		}

		void ircClient_OnChannelMessage(object sender, IrcEventArgs e)
		{
			var message = new ChannelMessage(e.Data.Nick, e.Data.Message);
			screenDirector.RouteMessage(e.Data.Channel, message);
		}

		void ircClient_OnDisconnected(object sender, EventArgs e)
		{
			var message = new ServerMessage("IRC Disconnected");
			screenDirector.RouteMessage(serverName, message);
		}

		void ircClient_OnConnectionError(object sender, EventArgs e)
		{
			var message = new ServerMessage("IRC Connection Error");
			screenDirector.RouteMessage(serverName, message);
		}

		void ircClient_OnErrorMessage(object sender, IrcEventArgs e)
		{
			var message = new ServerMessage("IRC Error: " + e.Data.Message);
			screenDirector.DirectMessageToTab(message);
		}

		void ircClient_OnError(object sender, ErrorEventArgs e)
		{
			var message = new ServerMessage("IRC Error: " + e.Data.Message);
			screenDirector.DirectMessageToTab(message);
		}

		void ircClient_OnConnected(object sender, EventArgs e)
		{
			var message = new ServerMessage("IRC Connected");
			screenDirector.RouteMessage(serverName, message);
		}

		void ircClient_OnConnecting(object sender, EventArgs e)
		{
			var message = new ServerMessage("IRC Connecting");
			screenDirector.RouteMessage(serverName, message);
		}

		void ircClient_OnTopic(object sender, TopicEventArgs e)
		{
			var message = new TopicMessage(e.Topic);
			screenDirector.RouteMessage(e.Channel, message);
		}

		#endregion

		public void Connect()
		{
			VsircServerConfiguration.GetInstance().ReadIrcServerConfiguration();
			var configuration = VsircServerConfiguration.GetInstance();

			serverName = configuration.Server;

			_ircThread = new Thread(Listen);
			_ircThread.Start(VsircServerConfiguration.GetInstance());
		}

		private bool IsConnected()
		{
			return ircClient != null && ircClient.IsConnected;
		}

		public void Disconnect()
		{
			if (IsConnected())
			{
				ircClient.RfcQuit();
				screenDirector.RemoveAllTabs();
			}
		}

		public void Part(string channelName)
		{
			if (IsConnected())
			{
				ircClient.RfcPart(channelName);
			}
		}

		public void SendMessage(string destination, string messageText)
		{
			try
			{
				if (ircClient != null && ircClient.IsConnected)
				{
					if (messageText.StartsWith("/join "))
					{
						string[] texts = messageText.Split(ScreenMessage.WhitespaceChar);
						ircClient.RfcJoin(texts[1]);
					}
					else
					{
						ircClient.SendMessage(SendType.Message, destination, messageText);

						var message = new PrivateMessage(ircClient.Nickname, messageText);

						screenDirector.DirectMessageToTab(message);
					}
					//if (messageText.StartsWith("/msg "))
					//{
					//    string[] texts = messageText.Split(' ');
					//    ircClient.RfcPrivmsg(texts[1], messageText.Substring(texts[0].Length + texts[1].Length));
					//}
					//else if (messageText.StartsWith("/nick "))
					//{
					//    string[] texts = messageText.Split(' ');
					//    ircClient.RfcNick(texts[1]);
					//    IrcServerConfiguration.GetInstance().OriginalNick = texts[1];
					//}
				}
				else
				{
					var message = new ServerMessage("Not Connected");

					screenDirector.DirectMessageToTab(message);
				}
			}
			catch
			{
				var message = new ServerMessage("Error sending message");

				screenDirector.DirectMessageToTab(message);
			}
		}
	}
}
